package com.source.multithread.randomaccesscopyfile;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
/**
 * 多线程复制文件
 * https://www.cnblogs.com/chenss15060100790/articles/7533362.html
 * 文件复制完全成功的，保证了完整性。
 * https://ifeve.com/file-channel/
 * @author ChenSS 2016/11/7
 * @version 1.0
 */
public class UsingThreadRandom {
    public static void main(String[] args) throws Exception {
     /*   File from=new File("D:\\test-data\\ActiveMQ.pdf"); // 8498338
        File to=new File("D:\\test-data\\to\\"+from.getName());*/
        File file = new File("D:\\test-data\\ActiveMQ.pdf");
        startThread(4, file.length(), "D:\\test-data\\ActiveMQ.pdf", "D:\\test-data\\to\\ActiveMQ.pdf");
    }

    /**
     * 开启多线程下载
     * 
     * @param threadnum 线程数
     * @param fileLength 文件大小（用于确认每个线程下载多少东西）
     * @param sourseFilePath 源文件目录
     * @param targerFilePath 目标文件目录
     */
    public static void startThread(int threadnum, long fileLength,
            String sourseFilePath, String targerFilePath) {
        System.out.println("================");
        long modLength = fileLength % threadnum;
        long targetLength = fileLength / threadnum;
        for (int i = 0; i < threadnum; i++) {
            System.out.println((targetLength * i) + "-----"
                    + (targetLength * (i + 1)));
            new FileWriteThread((targetLength * i), (targetLength * (i + 1)),
                    sourseFilePath, targerFilePath).start();
        }
        if (modLength != 0) {
            new FileWriteThread((targetLength * 4), modLength, sourseFilePath,
                    targerFilePath).start();
        }
    }


    /**
     * 写线程：指定文件开始位置、目标位置、源文件、目标文件，  
     */
    static class FileWriteThread extends Thread {
        private long begin;
        private long end;
        private RandomAccessFile soursefile;
        private RandomAccessFile targerFile;

        public FileWriteThread(long begin, long end, String sourseFilePath,
                String targerFilePath) {
            this.begin = begin;
            this.end = end;
            try {
                this.soursefile = new RandomAccessFile(sourseFilePath, "rw");
                this.targerFile = new RandomAccessFile(targerFilePath, "rw");
            } catch (FileNotFoundException e) {
            }
        }

        public void run() {
            try {
                soursefile.seek(begin);
                targerFile.seek(begin);
                int hasRead = 0;
                byte[] buffer = new byte[1024];
                while (begin < end && -1 != (hasRead = soursefile.read(buffer))) {
                    begin += hasRead;
                    targerFile.write(buffer, 0, hasRead);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    soursefile.close();
                    targerFile.close();
                } catch (Exception e) {
                }
            }
        }
    }
}